using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Services;
using JigLibX.Physics;
using Utilities;
using WAS.Logic;
using WAS.Logic.SampleLevel;


namespace WAS
{

  public interface IAudioManager
  {
    void OnWarp(float volume);

    void OnNukeExplode(float volume);

    void OnPlasmaExplode();

    void OnNukeLaunch();

    void OnPlasmaShoot();

    void OnProjectileShoot();

    void OnLaserShoot();

    void OnLightningShoot();

    void OnShockwaveShoot(float volume);

    void OnSlowMotionBegin();

    void OnFlashBegin();

    void OnBepBegin(float volume);

    void OnbepBegin(float volume);

    void OnMusicaBaseBegin(float volume);

    void OnMusicaIntermediaBegin(float volume);

    void OnMusicaDinamicaBegin(float volume);

    void stopAllSounds();

    void pauseAllSounds();

    void resumeAllSounds();

    void OnaudioOff();

    void OnaudioOn();

  }


  public class AudioManager : CameraConsumer, IAudioManager
  {
    protected ArrayList<SoundEffectInstance> laser, machine_gun, lightning, shockwave;
    protected ArrayList<SoundEffectInstance> laser_expl;
    protected ArrayList<SoundEffectInstance> laser_shoot;
    protected ArrayList<SoundEffectInstance> nuke_launch;
    protected ArrayList<SoundEffectInstance> nuke_expl;
    protected ArrayList<SoundEffectInstance> warp;
    protected ArrayList<SoundEffectInstance> slow_motion;
    protected ArrayList<SoundEffectInstance> bep;
    protected ArrayList<SoundEffectInstance> flash_effect;
    protected ArrayList<SoundEffectInstance> musica_base;
    protected ArrayList<SoundEffectInstance> musica_dinamica;
    protected ArrayList<SoundEffectInstance> musica_intermedia;

    protected string slow_motion_p, laser_p, machine_gun_p, laser_expl_p, nuke_launch_p, nuke_expl_p, warp_p, lightning_path, laser_path, shockwave_p;
    protected string flash_effect_p, bep_p, musica_base_p, musica_dinamica_p, musica_intermedia_p;

    public AudioManager(Microsoft.Xna.Framework.Game game)
        : base(game)
    {
        game.Services.AddService(typeof(IAudioManager), this);
        this.UpdateOrder = (int)ComponentOrders.SCENE;
        this.DrawOrder = (int)ComponentOrders.SCENE;
    }

    static public bool AudioState
    {
        get { return AudioManager.Volume == 1; }
        private set { }
    }

    public void resumeAllSounds()
    {
        for (int i = 0; i < bep.Count; i++)
        {
            if (bep[i].State == SoundState.Paused)
                bep[i].Resume();
        }

        for (int i = 0; i < musica_base.Count; i++)
        {
            if (musica_base[i].State == SoundState.Paused)
                musica_base[i].Resume();
        }

        for (int i = 0; i < musica_intermedia.Count; i++)
        {
            if (musica_intermedia[i].State == SoundState.Paused)
                musica_intermedia[i].Resume();
        }

        for (int i = 0; i < musica_dinamica.Count; i++)
        {
            if (musica_dinamica[i].State == SoundState.Paused)
                musica_dinamica[i].Resume();
        }

        for (int i = 0; i < flash_effect.Count; i++)
        {
            if (flash_effect[i].State == SoundState.Paused)
                flash_effect[i].Resume();
        }

        for (int i = 0; i < slow_motion.Count; i++)
        {
            if (slow_motion[i].State == SoundState.Paused)
                slow_motion[i].Resume();
        }

        for (int i = 0; i < warp.Count; i++)
        {
            if (warp[i].State == SoundState.Paused)
                warp[i].Resume();
        }
        for (int i = 0; i < nuke_expl.Count; i++)
        {
            if (nuke_expl[i].State == SoundState.Paused)
                nuke_expl[i].Resume();
        }


    }
    public void pauseAllSounds()
    {
        for (int i = 0; i < bep.Count; i++)
        {
            if(bep[i].State == SoundState.Playing)
                bep[i].Pause();
        }

        for (int i = 0; i < musica_base.Count; i++)
        {
            if (musica_base[i].State == SoundState.Playing)
                musica_base[i].Pause();
        }

        for (int i = 0; i < musica_intermedia.Count; i++)
        {
            if (musica_intermedia[i].State == SoundState.Playing)
                musica_intermedia[i].Pause();
        }

        for (int i = 0; i < musica_dinamica.Count; i++)
        {
            if (musica_dinamica[i].State == SoundState.Playing)
                musica_dinamica[i].Pause();
        }

        for (int i = 0; i < flash_effect.Count; i++)
        {
            if (flash_effect[i].State == SoundState.Playing)
                flash_effect[i].Pause();
        }

        for (int i = 0; i < slow_motion.Count; i++)
        {
            if (slow_motion[i].State == SoundState.Playing)
                slow_motion[i].Pause();
        }

        for (int i = 0; i < warp.Count; i++)
        {
            if (warp[i].State == SoundState.Playing)
                warp[i].Pause();
        }
        for (int i = 0; i < nuke_expl.Count; i++)
        {
            if (nuke_expl[i].State == SoundState.Playing)
                nuke_expl[i].Pause();
        }


    }
    public void stopAllSounds()
    {
        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Stop();            
        }
        bep.Clear();

        for (int i = 0; i < musica_base.Count; i++)
        {
            musica_base[i].Stop();
        }
        musica_base.Clear();

        for (int i = 0; i < musica_intermedia.Count; i++)
        {
            musica_intermedia[i].Stop();
        }
        musica_intermedia.Clear();

        for (int i = 0; i < musica_dinamica.Count; i++)
        {
            musica_dinamica[i].Stop();
        }
        musica_dinamica.Clear();

        for (int i = 0; i < flash_effect.Count; i++)
        {
            flash_effect[i].Stop();
        }
        flash_effect.Clear();

        for (int i = 0; i < slow_motion.Count; i++)
        {
            slow_motion[i].Stop();
        }
        slow_motion.Clear();

        for (int i = 0; i < warp.Count; i++)
        {
            warp[i].Stop();
        }
        warp.Clear();
        for (int i = 0; i < nuke_expl.Count; i++)
        {
            nuke_expl[i].Stop();
        }
        nuke_expl.Clear();


    }

    public void OnaudioOff()
    {

        if (AudioManager.Volume > 0)
            volume = 0;
        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Volume = 0;
        }

        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Volume = 0;
        }

        for (int i = 0; i < musica_base.Count; i++)
        {
            musica_base[i].Volume = 0;
        }

        for (int i = 0; i < musica_intermedia.Count; i++)
        {
            musica_intermedia[i].Volume = 0;
        }

        for (int i = 0; i < musica_dinamica.Count; i++)
        {
            musica_dinamica[i].Volume = 0;
        }

        for (int i = 0; i < flash_effect.Count; i++)
        {
            flash_effect[i].Volume = 0;
        }

        for (int i = 0; i < slow_motion.Count; i++)
        {
            slow_motion[i].Volume = 0;
        }
        for (int i = 0; i < warp.Count; i++)
        {
            warp[i].Volume = 0;
        }
        for (int i = 0; i < nuke_expl.Count; i++)
        {
            nuke_expl[i].Volume = 0;
        }

    }
    public void OnaudioOn()
    {
        if (MediaPlayer.State == MediaState.Playing)
            return;

        if (AudioManager.Volume == 0)
            volume = 1;
         
        for (int i = 0; i < warp.Count; i++)
        {
            warp[i].Volume = 1;
        }

        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Volume = 1;
        }

        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Volume = 1;
        }

        for (int i = 0; i < musica_base.Count; i++)
        {
            musica_base[i].Volume = 0.5f;
        }
        for (int i = 0; i < musica_intermedia.Count; i++)
        {
            musica_intermedia[i].Volume = 0.5f;
        }
        for (int i = 0; i < musica_dinamica.Count; i++)
        {
            musica_dinamica[i].Volume = 0.5f;
        }

        for (int i = 0; i < flash_effect.Count; i++)
        {
            flash_effect[i].Volume = 1;
        }

        for (int i = 0; i < slow_motion.Count; i++)
        {
            slow_motion[i].Volume = 1;
        }


        for (int i = 0; i < nuke_expl.Count; i++)
        {
            nuke_expl[i].Volume = 1;
        }
    }
    public override void Initialize()
    {
      var game = Game;

      slow_motion_p = "Audio/slowmotion";
      laser_p = "Audio/laser_blast";
      machine_gun_p = "Audio/machine_gun";
      laser_expl_p = "Audio/laser_blast2";
      nuke_launch_p = "Audio/nuke_launch";
      nuke_expl_p = "Audio/bomb2";
      warp_p = "Audio/warp";
      lightning_path = "Audio/lightning";
      laser_path = "Audio/laser";
      shockwave_p = "Audio/shockwave";
      flash_effect_p = "Audio/flash_effect";
        bep_p = "Audio/bep";
        bep_p = "Audio/bep";
        musica_base_p = "Audio/musica_base";
        musica_dinamica_p = "Audio/musica_dinamica";
        musica_intermedia_p = "Audio/musica_intermedia";

      laser = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(laser_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(laser_p).CreateInstance(), Game.Content.Load<SoundEffect>(laser_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(laser_p).CreateInstance(), Game.Content.Load<SoundEffect>(laser_p).CreateInstance() };
      machine_gun = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(machine_gun_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(machine_gun_p).CreateInstance(), Game.Content.Load<SoundEffect>(machine_gun_p).CreateInstance()};
      laser_expl = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(laser_expl_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(laser_expl_p).CreateInstance(), Game.Content.Load<SoundEffect>(laser_expl_p).CreateInstance() };
      nuke_launch = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(nuke_launch_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(nuke_launch_p).CreateInstance(), Game.Content.Load<SoundEffect>(nuke_launch_p).CreateInstance(), Game.Content.Load<SoundEffect>(nuke_launch_p).CreateInstance() };
      nuke_expl = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(nuke_expl_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>("Audio/bomb-01").CreateInstance(), Game.Content.Load<SoundEffect>("Audio/bomb-03").CreateInstance() };
      warp = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(warp_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(warp_p).CreateInstance(), Game.Content.Load<SoundEffect>(warp_p).CreateInstance()};
      lightning = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(lightning_path).CreateInstance(), 
          Game.Content.Load<SoundEffect>(lightning_path).CreateInstance()};
      laser_shoot = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(laser_path).CreateInstance(), 
          Game.Content.Load<SoundEffect>(laser_path).CreateInstance(), Game.Content.Load<SoundEffect>(laser_path).CreateInstance() };
      shockwave = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(shockwave_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(shockwave_p).CreateInstance(), Game.Content.Load<SoundEffect>(shockwave_p).CreateInstance() };
      slow_motion = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(slow_motion_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(slow_motion_p).CreateInstance(), Game.Content.Load<SoundEffect>(slow_motion_p).CreateInstance() };
      flash_effect = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(flash_effect_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(flash_effect_p).CreateInstance(), Game.Content.Load<SoundEffect>(flash_effect_p).CreateInstance() };
      bep = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(bep_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(bep_p).CreateInstance(), Game.Content.Load<SoundEffect>(bep_p).CreateInstance() };
      musica_base = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(musica_base_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(musica_base_p).CreateInstance(), Game.Content.Load<SoundEffect>(musica_base_p).CreateInstance() };
      musica_intermedia = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(musica_intermedia_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(musica_intermedia_p).CreateInstance(), Game.Content.Load<SoundEffect>(musica_intermedia_p).CreateInstance() };
      musica_dinamica = new ArrayList<SoundEffectInstance>(15) { Game.Content.Load<SoundEffect>(musica_dinamica_p).CreateInstance(), 
          Game.Content.Load<SoundEffect>(musica_dinamica_p).CreateInstance(), Game.Content.Load<SoundEffect>(musica_dinamica_p).CreateInstance() };     
      base.Initialize();
    }

    static private float volume;

    static public float Volume
    {
        get { return volume; }
        set
        {
            volume = value;
        }
    }

      
    protected override void Dispose(bool disposing)
    {
      Game.Services.RemoveService(typeof(IAudioManager));
      base.Dispose(disposing);
    }

    public void OnWarp(float volume)
    {
        PlaySoundEffectInstance(warp, volume, 0.0f, 0.0f, warp_p);
    }

    public void OnNukeExplode(float volume)
    {
        for (int i = 0; i < nuke_expl.Count; i++)
        {
            if (nuke_expl[i].State != SoundState.Playing)
            {
                nuke_expl[i].Pan = 0.0f;
                nuke_expl[i].Pitch = 0.0f;
                
                nuke_expl[i].Volume = (AudioManager.Volume / volume) ;
                nuke_expl[i].Play();
                return;
            }
        }
        //PlaySoundEffectInstance(nuke_expl, 0.0f, 0.0f, nuke_expl_p);
    }

    public void OnPlasmaExplode()
    {
        
        PlaySoundEffectInstance(laser_expl, 0.0f, 0.0f, laser_expl_p);
    }

    public void OnNukeLaunch()
    {
        PlaySoundEffectInstance(nuke_launch, 0.0f, 0.0f, nuke_launch_p);
    }

    public void OnPlasmaShoot()
    {
        PlaySoundEffectInstance(laser, 0.0f, 0.0f, laser_p);
    }

    public void OnProjectileShoot()
    {
        PlaySoundEffectInstance(machine_gun, 2.0f, 0, 0, machine_gun_p);
    }

    public void OnLightningShoot()
    {
        PlaySoundEffectInstance(lightning, 2.0f, 0, 0, lightning_path);
    }

    public void OnLaserShoot()
    {
        PlaySoundEffectInstance(laser_shoot, 3.0f, 0, 0, laser_path);
    }

    public void OnShockwaveShoot(float volume)
    {

      PlaySoundEffectInstance(laser_expl, volume, 0, 0, shockwave_p);
    }

    public void OnSlowMotionBegin()
    {
        for (int i = 0; i < slow_motion.Count; i++)
        {
            slow_motion[i].Stop();
        }
        slow_motion.Clear();

        PlaySoundEffectInstance(slow_motion, 0, 0, slow_motion_p);
    }    

    public void OnBepBegin(float volume)
    {
        PlaySoundEffectInstance(bep, volume, 0, 0, bep_p);
    }

    public void OnbepBegin(float volume)
    {
        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Stop();
        }
        bep.Clear();
        PlaySoundEffectInstance(bep, volume, 0, 0, bep_p);
    }

    public void OnFlashBegin()
    {
        for (int i = 0; i < bep.Count; i++)
        {
            bep[i].Stop();
        }
        bep.Clear();
        for (int i = 0; i < flash_effect.Count; i++)
        {
            flash_effect[i].Stop();
        }
        flash_effect.Clear();

        PlaySoundEffectInstance(flash_effect, 0, 0, flash_effect_p);
    }

    public void OnMusicaBaseBegin(float volume)
    {
        PlaySoundEffectInstance(musica_base, volume, 0, 0, musica_base_p,true);
    }
    public void OnMusicaIntermediaBegin(float volume)
    {
        for (int i = 0; i < musica_base.Count; i++)
        {
            musica_base[i].Stop();
        }
        PlaySoundEffectInstance(musica_intermedia, volume, 0, 0, musica_intermedia_p, true);
    }
    public void OnMusicaDinamicaBegin(float volume)
    {
        for (int i = 0; i < musica_intermedia.Count; i++)
        {
            musica_intermedia[i].Stop();
        }
        PlaySoundEffectInstance(musica_dinamica, volume, 0, 0, musica_dinamica_p,true);
    } 
    private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> effect_list, float pitch, float pan, string path)
    {


        for (int i = 0; i < effect_list.Count; i++)
        {
            if (!(effect_list[i].State == SoundState.Playing))
            {
                effect_list[i].Pitch = pitch;
                effect_list[i].Pitch = pan;
                effect_list[i].Volume = AudioManager.Volume;
                effect_list[i].Play();
                return;
            }
        }


        if (effect_list.Count == 3)
        {
            effect_list[0].Stop();
            effect_list.RemoveAt(0);
        }

        effect_list.Add(Game.Content.Load<SoundEffect>(path).CreateInstance());
        PlaySoundEffectInstance(effect_list, pitch, pan, path);
    }


    private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> effect_list, float volume_div, float pitch, float pan, string path)
    {


        for (int i = 0; i < effect_list.Count; i++)
        {
            if (!(effect_list[i].State == SoundState.Playing))
            {
                effect_list[i].Pitch = pitch;
                effect_list[i].Pitch = pan;
                effect_list[i].Volume = (AudioManager.Volume / volume_div);
                effect_list[i].Play();
                return;
            }
        }

        if (effect_list.Count == 3)
        {
            effect_list[0].Stop();
            effect_list.RemoveAt(0);
        }

        effect_list.Add(Game.Content.Load<SoundEffect>(path).CreateInstance());
        PlaySoundEffectInstance(effect_list, volume_div, pitch, pan, path);
    }
    private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> effect_list, float volume_div, float pitch, float pan, string path, bool repeat)
    {
        for (int i = 0; i < effect_list.Count; i++)
        {
            if (!(effect_list[i].State == SoundState.Playing))
            {
                effect_list[i].Pitch = pitch;
                effect_list[i].Pitch = pan;
                effect_list[i].Volume = (AudioManager.Volume / volume_div);
                effect_list[i].IsLooped = repeat;
                effect_list[i].Play();
                return;
            }
        }

        if (effect_list.Count == 3)
        {
            effect_list[0].Stop();
            effect_list.RemoveAt(0);
        }

        effect_list.Add(Game.Content.Load<SoundEffect>(path).CreateInstance());
        PlaySoundEffectInstance(effect_list, volume_div, pitch, pan, path,repeat);
    }
  }
}